﻿// dotnet5="../../Backend" ; dotnet $DOTNET_CSC_DLL -nologo -t:library -r:"$dotnet5/System.dll" -r:"$dotnet5/System.Core.dll" -r:"$dotnet5/System.Text.Json.dll" -r:"$dotnet5/System.Collections.dll" -r:"$dotnet5/mscorlib.dll" -r:"$dotnet5/netstandard.dll" -r:"../../Backend/GameData.dll" -r:"../../The Scroll of Taiwu_Data/Managed/TaiwuModdingLib.dll" -r:"$dotnet5/System.Private.CoreLib.dll" -r:"$dotnet5/System.Runtime.dll" -r:"$dotnet5/System.Runtime.InteropServices.dll" -r:"$dotnet5/System.Linq.dll" -r:"$dotnet5/System.Text.Encodings.Web.dll" -r:"$dotnet5/System.IO.FileSystem.dll" -r:"$dotnet5/Redzen.dll" -unsafe -optimize -deterministic -debug NeutronBlackMarket.cs *.CS -out:NeutronBlackMarket.dll -debug -define:BACKEND -nowarn:CS1702 # -define:SPEEDTEST -define:Json
using System;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Text.Json;

using GameData.Common;
using GameData.Domains;
using GameData.Domains.Character;
using GameData.Domains.Map;
using GameData.GameDataBridge;
using GameData.Utilities;
using System.Collections.Generic;
using TaiwuModdingLib.Core.Plugin;
using static Utils.Logger;
namespace Neutron3529.BlackMarket;

[PluginConfig("Neutron3529.BlackMarket", "Neutron3529", "0.1")]
public class Backend : TaiwuRemakePlugin {
    public override void Initialize(){}
    public override void Dispose(){}
    public static unsafe string EncodeCharFromIdV1(int character){ // version 1 only.
        if(GameData.Domains.DomainManager.Character.TryGetElement_Objects(character, out var ch)){
            ICData data=new CharacterData(); // version 1.
            data.From(ch);
            var size=data.Size();
            var bytes=new byte[size];
            fixed(byte*fxptr=bytes){
                data.S(fxptr);
            }
            return Convert.ToBase64String(bytes);
        } else {
            throw new Exception("请求人物不存在");
        }
    }
    public static unsafe ICData DecodeData(string b64){
        var data=Convert.FromBase64String(b64);
        fixed(byte*fxptr=data){
            var version=*(int*)fxptr;
            switch (version) {
                case 1:
                    var ret=new CharacterData();
                    ret.Des(fxptr+4);
                    return ret;
                default:throw new Exception("请求版本有误");
            }
        }
    }
    static MethodInfo RemoveElement_WaitingReincarnationChars=typeof(GameData.Domains.Character.CharacterDomain).GetMethod("RemoveElement_WaitingReincarnationChars",(BindingFlags)(-1));
    // GameData.Utilities.SortedSetAsDictionary<GameData.Utilities.IntPair> _waitingReincarnationChars
    static FieldInfo _waitingReincarnationChars=typeof(GameData.Domains.Character.CharacterDomain).GetField("_waitingReincarnationChars",(BindingFlags)(-1));
    public unsafe static bool Sell(GameData.Domains.Character.Character ch, GameData.Common.DataContext ctx){
        if(ch!=null){
            var cid=ch.GetId();
            GameData.Domains.DomainManager.Character.RecordDeletedFromOthersPreexistence(ctx, ref ch.GetPreexistenceCharIds()); // 记录：这些人的轮回信息可以删除
            var death_date=GameData.Domains.DomainManager.World.GetCurrDate();
            GameData.Domains.DomainManager.Character.Die(ctx, ch, false, death_date); // 令当前人物死亡

            // 当前人物死亡时会在_waitingReincarnationChars中添加IntPair(death_date,cid)，删除之。
            RemoveElement_WaitingReincarnationChars.Invoke(GameData.Domains.DomainManager.Character, new object[]{new GameData.Utilities.IntPair(death_date, cid), ctx});
            // 或者可以采用下面的低效删除法
            // var waitingReincarnationChars=(GameData.Utilities.SortedSetAsDictionary<GameData.Utilities.IntPair>)(_waitingReincarnationChars.GetValue(GameData.Domains.DomainManager.Character));
            // foreach (GameData.Utilities.IntPair del in waitingReincarnationChars) {
            //     if (del.Second == presetReincarnationCharId) {
            //         RemoveElement_WaitingReincarnationChars.Invoke(GameData.Domains.DomainManager.Character, new object[]{del,ctx})
            //         break;
            //     }
            // }

            // 模拟本人轮回数据删除过程
            var preexistenceCharIds=default(GameData.Domains.Character.PreexistenceCharIds);
            preexistenceCharIds.Count=1;
            preexistenceCharIds.CharIds[0]=cid;
            GameData.Domains.DomainManager.Character.RecordDeletedFromOthersPreexistence(ctx, ref preexistenceCharIds); // 标记轮回已删除
            return true;
        } else {
            return false;
        }
    }
    public static void Into(ICData icd, GameData.Domains.Character.Character ch, GameData.Common.DataContext ctx){ // 覆写NPC数据
        icd.Into(ch,ctx);
    }
    // cdata==null 时生成山大王id的随机敌人作为黑奴
    // cdata不为null是使用cdata中的数据。
    public static int CreateChar(ICData cdata=null, sbyte ideals=-1){ // 创建随机敌人以预览
        if(ideals==-1){
            ideals=cdata==null?(sbyte)0:cdata.GetIdeal;
        }
        int cid=GameData.Domains.TaiwuEvent.EventHelper.EventHelper.CreateNonIntelligentCharacter((short)(242+ideals));
        // 243=少林弃徒，这样可以根据人物心仪门派完成人物创建
        if(cdata!=null && GameData.Domains.DomainManager.Character.TryGetElement_Objects(cid, out var ch)){
            Into(cdata, ch, GameData.Domains.DomainManager.TaiwuEvent.MainThreadDataContext);
        }
        return cid;
    }
    public static bool ModifyChar(GameData.Domains.Character.Character ch, ICData cdata){ // 将默认人物修改为当前数据对应的人物
        if(cdata!=null && ch!=null){
            Into(cdata, ch, GameData.Domains.DomainManager.TaiwuEvent.MainThreadDataContext);
            return true;
        }
        logwarn((cdata==null?"cdata==null ":"")+(ch==null?"character==null":""));
        return false;
    }
    public static bool ConvertChar(GameData.Domains.Character.Character ch){ // 将非智能NPC转化为智能NPC
        if(ch==null)return false;
        GameData.Domains.DomainManager.Character.ConvertRandomEnemy(GameData.Domains.DomainManager.TaiwuEvent.MainThreadDataContext, ch, GameData.Domains.DomainManager.Taiwu.GetTaiwu().GetLocation());
        // Into(test_decode, ch, GameData.Domains.DomainManager.TaiwuEvent.MainThreadDataContext);
        ch.SetFullName(ch.GetIdealSect()==11
        ?GameData.Domains.DomainManager.Character.GenerateRandomZangName(GameData.Domains.DomainManager.TaiwuEvent.MainThreadDataContext, ch.GetGender())
        :GameData.Domains.DomainManager.Character.GenerateRandomHanName(GameData.Domains.DomainManager.TaiwuEvent.MainThreadDataContext, -1 , -1, ch.GetGender()
        ),GameData.Domains.DomainManager.TaiwuEvent.MainThreadDataContext);
        return true;
    }
    public static bool RemoveChar(GameData.Domains.Character.Character ch){ // 删除非智能NPC
        if(ch!=null && ch.GetCreatingType()!=1){
            GameData.Domains.TaiwuEvent.EventHelper.EventHelper.RemoveNonIntelligentCharacter(ch);
            return true;
        }
        return false;
    }

    public static CharacterData test_decode;
    public static void TestV1(int cid){
        GameData.Domains.DomainManager.Character.TryGetElement_Objects(cid, out var ch);
        var cdata=EncodeCharFromIdV1(cid);
        logger("encode result: "+cdata);
        test_decode=(CharacterData)DecodeData(cdata);
        logger($"test_decode.featureIds.Length={test_decode.featureIds.Length} {ch.GetFeatureIds().Count}");
        logger($"cmp test_decode.featureIds with ch.GetFeatureIds : {ch.GetFeatureIds().SequenceEqual(test_decode.featureIds)}");
        logger($"cmp test_decode.potentialFeatureIds with ch.GetPotentialFeatureIds : {ch.GetPotentialFeatureIds().SequenceEqual(test_decode.potentialFeatureIds)}");
    }
    public static void TestV1_write(int cid){
        if(test_decode==null)return;
        GameData.Domains.DomainManager.Character.TryGetElement_Objects(cid, out var ch);
        Into(test_decode, ch, GameData.Domains.DomainManager.TaiwuEvent.MainThreadDataContext);
    }
}
